<?php

namespace Com\Rsa;

class Rsa {

    /**
     * private key 
     */
    private $_privKey;

    /**
     * public key 
     */
    private $_pubKey;

    /**
     * the keys saving path 
     */
    private $_keyPath;

    /*
     */
    private $_passphrase;

    /**
     * the construtor,the param $path is the keys saving path 
     */
    public function __construct($path) {
        if (empty($path) || !is_dir($path)) {
            throw new \Exception('Must set the keys save path');
        }
        $this->_passphrase = "sign";
        $this->_keyPath = $path;
    }

    /**
     * 设置密钥文件路径
     * @modify trainyao 2015-09-27 创建
     * @param string $path  密钥文件路径
     * @return 无
     */
    public function setKeyPath($path) {
        $this->_keyPath = $path;
    }

    /**
     * create the key pair,save the key to $this->_keyPath 
     */
    public function createKey() {
        $privateKeyFile = $this->_keyPath . '/' . 'private_key.pem';
        $publicKeyFile = $this->_keyPath . '/' . 'public_key.pem';

        if (file_exists($privateKeyFile) && file_exists($publicKeyFile)) {
            return true;
        }

        $configargs = array(
            //'digest_alg' => 'sha1', 
            'private_key_type' => OPENSSL_KEYTYPE_RSA,
            'private_key_bits' => 2048,
                //"config" => "C:/wamp/bin/php/php5.4.16/extras/openssl.cnf"
        );
        /*
          // 创建私钥文件
          $r = openssl_pkey_new($configargs);
          //var_dump($r);
          openssl_pkey_export($r,$privKey,$this->_passphrase,$configargs);
          //var_dump($privKey);
          file_put_contents($privateKeyFile, $privKey);
          $this->_privKey = openssl_pkey_get_private($privKey,$this->_passphrase);
          //var_dump($this->_privKey);exit;
          // 创建公钥文件
          $rp = openssl_pkey_get_details($r);
          $pubKey = $rp['key'];
          //var_dump($pubKey) ;
          file_put_contents($this->_keyPath . '/' .  'pub.key', $pubKey);
          $this->_pubKey = openssl_pkey_get_public($pubKey);
          //var_dump($this->_pubKey); */
    }

    /**
     * setup the private key 
     */
    public function setupPrivKey() {
        if (is_resource($this->_privKey)) {
            return true;
        }
        $file = $this->_keyPath . '/' . 'private_key.pem';
        $prk = file_get_contents($file);
        $this->_privKey = openssl_pkey_get_private($prk, $this->_passphrase);
        return true;
    }

    /**
     * setup the public key 
     */
    public function setupPubKey() {
        if (is_resource($this->_pubKey)) {
            return true;
        }
        $file = $this->_keyPath . '/' . 'public_key.pem';
        $puk = file_get_contents($file);
        $this->_pubKey = openssl_pkey_get_public($puk);
        return true;
    }

    /**
     * encrypt with the private key 
     */
    public function privEncrypt($data) {
        if (!is_string($data)) {
            return null;
        }

        $this->setupPrivKey();
        // var_dump($this->_privKey);
        $r = openssl_private_encrypt($data, $encrypted, $this->_privKey);
        if ($r) {
            return base64_encode($encrypted);
        }
        return null;
    }

    /**
     * decrypt with the private key 
     */
    public function privDecrypt($encrypted) {
        if (!is_string($encrypted)) {
            return null;
        }

        $this->setupPrivKey();

        $encrypted = base64_decode($encrypted);

        $r = openssl_private_decrypt($encrypted, $decrypted, $this->_privKey);
        if ($r) {
            return $decrypted;
        }
        return null;
    }

    /**
     * encrypt with public key 
     */
    public function pubEncrypt($data) {
        if (!is_string($data)) {
            return null;
        }
        $this->setupPubKey();
        $r = openssl_public_encrypt($data, $encrypted, $this->_pubKey);
        if ($r) {
            return base64_encode($encrypted);
        }
        return null;
    }

    /**
     * decrypt with the public key 
     */
    public function pubDecrypt($crypted) {
        if (!is_string($crypted)) {
            return null;
        }

        $this->setupPubKey();

        $crypted = base64_decode($crypted);

        $r = openssl_public_decrypt($crypted, $decrypted, $this->_pubKey);
        if ($r) {
            return $decrypted;
        }
        return null;
    }

    public function __destruct() {
        @ fclose($this->_privKey);
        @ fclose($this->_pubKey);
    }

}
